#!/usr/bin/ruby

require "sqlite3"
require 'pp'
require File.dirname(__FILE__) + "/shared.rb"

DEBUG = false 

SOXI_DUR_RE = /^Duration\s*: ([0-9][0-9]:[0-9][0-9]:[0-9][0-9]\.[0-9][0-9])/
SOXI_DUR_RE_IDX = 1

def seconds2time(n)
    return Time.at(n)
end

def time2fname(t)
    year  = t.year.to_s
    month = pad2(t.month)
    mday  = pad2(t.mday)
    hour  = pad2(t.hour)
    min   = pad2(t.min)
    
    dir = "#{REC_DIR}/#{year}/#{month}/#{mday}/"
    return dir, "#{dir}/#{hour}#{min}.#{AUD_FORMAT}"
end

def time_round(t)
    block_seconds = BLOCK_DUR * 60
    lag = t.to_i % block_seconds
    return t - lag
end

def get_lag()
    return Time.now().to_i % (BLOCK_DUR * 60)
end

# determines the actual length of a recording
def get_file_duration(fname)
    md = SOXI_DUR_RE.match(`soxi #{fname}`)
    if md
        h,m,s = md[SOXI_DUR_RE_IDX].split(':')
    else
        return 0
    end
    return s.to_i + 60*m.to_i + 60*60*h.to_i
end

# adds a recording to the database
def db_add(fname, t, duration)
    chat_len = get_file_duration(fname)
    db = SQLite3::Database.new(DB_FILE)
    cmd = "INSERT INTO\
        Recordings(file_name, start_t, rec_dur, chat_len, have_file) VALUES\
        (\"#{fname}\", #{t.to_i}, #{duration}, #{chat_len}, 1);"
    pp "db cmd = #{cmd}" if DEBUG
    db.execute(cmd)
end

def log(s)
    puts "#{Time.now()} : #{s}\n"   if DEBUG
    f = File.new(DAEMON_LOG, 'a')
    f.write("#{Time.now()} : #{s}\n")
    f.close()
end

def main
    assert( 3*OVERLAP_DUR < 60*BLOCK_DUR )

    prev_fname = nil
    prev_t = nil
    prev_lag = 0
    
    block_remaining = BLOCK_DUR * 60 - get_lag()
    sleep(block_remaining)  if block_remaining < OVERLAP_DUR
    while true
        log("starting new recording cycle")
        
        lag = get_lag()
        duration = BLOCK_DUR * 60 + OVERLAP_DUR - lag

        t = Time.now()
        dir, fname = time2fname(t)
        `mkdir --parents #{dir}`

        `#{MK_REC_RB} #{fname} #{duration} >/dev/null 2> /dev/null &`
        log("started recording to #{fname} with lag=#{lag} seconds")
        
        # wait for prev recording to finish and document it in the db
        if not prev_fname.nil?
            log("WARNING: excessive lag: #{lag}") if lag > OVERLAP_DUR
            log("waiting for previous recording to finish")
            #sleep( OVERLAP_DUR + prev_lag )
            sleep( 2 * OVERLAP_DUR )
            log("adding previous recording (#{prev_fname}) to database")
            db_add(prev_fname, prev_t, prev_duration) 
        end
        
        prev_fname = fname
        prev_t          = t
        prev_lag        = lag
        prev_duration   = duration

        if time_round(t).to_i != time_round(Time.now()).to_i
            log("WARNING: missed start of next recording cycle "+\
                "(lag=#{get_lag()}); starting ASAP")
        else
            # sleep until next round
            t_next = time_round(t) + BLOCK_DUR * 60
            log("going to sleep; plan to wake at #{t_next}")
            sleep( t_next.to_i - Time.now().to_i )
        end
    end
end

if __FILE__ == $0
    log("starting recorder-daemon -------------------------------")
    main
end
